#ifndef __MINISTATE_H__
#define __MINISTATE_H__

#include "State.h"
//#include "fnv.h"
#include <vector>
#include <tr1/unordered_map>
#include <set>
#include <stack>

struct MiniState {
    int rows,cols;
    Location tLeft;
    Location bRight;
    State* mainState;
    std::vector<std::vector<Square> > grid;
    std::map<int,std::vector<Location> > playerAntList;
    std::map<int,int> playerScores;
    std::vector<Location> antsInBattle;
    static std::map<size_t ,int> miniStateEvalCache;


    MiniState(State* state,const Location& topLeft,const Location& bottomRight,const std::vector<Location>& antsThatMatter);
    ~MiniState() {};

    //hash functions

    
    //useful for evaluating future states.
    int mockMakeMove(const Location& loc,int direction);
    void unmakeMockMove(const Location &loc,int direction,int savedAnt);

    //functions to translate world to map coordinates
    int mapX(const int& x) const {
	return (x<0?rows-abs(x%rows)-1:x%rows);
    }
    
    int mapY(const int&y) const {
	return (y<0?cols-abs(y%cols)-1:y%cols);
    }

    //path from loc1 to loc2
    bool findPath(const Location& loc1, const Location& loc2,
		  std::stack<int>& path,int& numNodesExplored,
		  int player_id=0) const;
    void extractPath(const Location& startLoc,const Location& endLoc,
                     const std::vector< std::vector<int> >& visited,std::stack<int>& path) const;
    Location getLocation(const Location &startLoc, int direction) const;
    double distance(const Location &loc1, const Location &loc2) const;
    void findThisAntsEnemiesInRadius(const Location& loc,const double& radius,std::vector<Location>& antList,int player_id) const;

    int eval(int player_id);
    int resolveBattles();

    std::pair<Location,int> translateMoveToMainMap(std::pair<Location,int> move);
    bool findClosestAnt(const Location& loc,Location& antLoc,std::stack<int>& path);
    bool myHillInView(const Location& loc,const double& radius) const;
    bool enemyHillInView(const Location& loc,const double& radius) const;
    bool operator==(const MiniState& x) const {
        return (this->grid == x.grid);
    }
    bool checkCache(int& score);
};

std::ostream& operator<<(std::ostream &os,const MiniState& state); 

namespace std {
    namespace tr1 {

        template<>
            struct hash<MiniState>:public std::unary_function<MiniState,std::size_t> {
            size_t operator()(const MiniState& x) const throw() {
                size_t hash=0;
                for(int i = 0;i<x.rows;i++) {
                    for (int j=0;j<x.cols;j++) {
                        hash+=std::tr1::hash<Square>()(x.grid[i][j]);
                    }
                }
                return hash;
            }
        };
    }
}
#endif
